﻿#pragma execution_character_set("utf-8")
#include "finiteaqs.h"
#include "ui_finiteaqs.h"
#include <QMessageBox>

FiniteAqs::FiniteAqs(QWidget *parent, HANDLE dev_handle)
    : QMainWindow(parent)
    , ui(new Ui::FiniteAqs)
    , usb5630_h(dev_handle)
{
    ui->setupUi(this);
    setWindowFlags(windowFlags() & ~Qt::WindowMinimizeButtonHint);

    plotTimer = new QTimer(this);
    connect(plotTimer, &QTimer::timeout, this, &FiniteAqs::plot_update);

    QFile f(":/qss/flatwhite.css");

    if (!f.exists())   {
        printf("Unable to set stylesheet, file not found\n");
    }
    else   {
        f.open(QFile::ReadOnly | QFile::Text);
        QTextStream ts(&f);
        qApp->setStyleSheet(ts.readAll());
    }

    QTimer::singleShot(10*60000, this, [=]{close();});
}

FiniteAqs::~FiniteAqs()
{
    if(Acq_thread->isRunning())
        Acq_thread->quit();
    if(convert_thread->isRunning())
        convert_thread->quit();
    delete ui;
}

void FiniteAqs::showEvent(QShowEvent *)
{
    QStringList headerlist;
    headerlist<<"time";
    for(int index = 1; index<65; index++)
    {
        headerlist<<QString::number(index);
    }
    ui->DataTable->setHorizontalHeaderLabels(headerlist);
    ui->DataAqsBtn->setEnabled(false);


    Dev5630 = new Acqure(nullptr, usb5630_h);
    Acq_thread = new QThread;
    Dev5630->moveToThread(Acq_thread);

    connect(Acq_thread, &QThread::finished, Dev5630, &QObject::deleteLater);
    connect(Dev5630, &Acqure::out_log, this, &FiniteAqs::log_update);
    connect(Dev5630, &Acqure::out_mat, this, &FiniteAqs::data_update);
    connect(Dev5630, &Acqure::out_mat, this, &FiniteAqs::curve_update);
    connect(this, &FiniteAqs::call_testAqc, Dev5630, &Acqure::AI_ReadBinary);
    connect(this, &FiniteAqs::call_loop_read, Dev5630, &Acqure::loop_read);

    converter = new Converter;
    convert_thread = new QThread;
    converter->moveToThread(convert_thread);

    connect(convert_thread, &QThread::finished, converter, &QObject::deleteLater);
    connect(Dev5630, &Acqure::out_mat, converter, &Converter::mat2pixmap);
    connect(converter, &Converter::out_pixmap, this, &FiniteAqs::map_update);

    convert_thread->start();
    Acq_thread->start();

    customPlot = ui->CPwidget;
    customPlot->setBackground(QBrush(QColor(0, 127, 192, 64)));
    // give the axes some labels:
    customPlot->xAxis->setLabel("time");
    customPlot->yAxis->setLabel("value");
    customPlot->legend->setVisible(true);//图例可见
    // set axes ranges, so we see all data:
    customPlot->yAxis->setRange(0, 65535);
    //设置x轴显示时间
    QSharedPointer<QCPAxisTickerDateTime> Ticker(new QCPAxisTickerDateTime);
    Ticker->setDateTimeFormat("h:m:s.z");//设置时间轴显示的格式
    Ticker->setDateTimeSpec(Qt::LocalTime);
    Ticker->setTickCount(10);//设置时间轴显示的格数
    customPlot->xAxis->setTickLabelRotation(35);//设置label 旋转35° 横着显示可能显示不全
    customPlot->xAxis->setTickLabels(true);
    customPlot->xAxis->setTicker(Ticker);
    // create graph and assign data to it:
    customPlot->addGraph();
    customPlot->graph(0)->setPen(QPen(Qt::red));
    customPlot->graph(0)->setLineStyle(QCPGraph::lsLine);    //使用直线将点连接
//    customPlot->graph(0)->setScatterStyle(QCPScatterStyle::ssCircle);  //○
    customPlot->addGraph();
    customPlot->graph(1)->setPen(QPen(Qt::green));
    customPlot->graph(1)->setLineStyle(QCPGraph::lsLine);    //使用直线将点连接
//    customPlot->graph(1)->setScatterStyle(QCPScatterStyle::ssDiamond);  //◇
    customPlot->addGraph();
    customPlot->graph(2)->setPen(QPen(Qt::blue));
    customPlot->graph(2)->setLineStyle(QCPGraph::lsLine);    //使用直线将点连接
//    customPlot->graph(2)->setScatterStyle(QCPScatterStyle::ssStar);  //*
    customPlot->addGraph();
    customPlot->graph(3)->setPen(QPen(QColor(255, 127, 0)));
    customPlot->graph(3)->setLineStyle(QCPGraph::lsLine);    //使用直线将点连接
//    customPlot->graph(3)->setScatterStyle(QCPScatterStyle::ssTriangleInverted); //△
    customPlot->addGraph();
    customPlot->graph(4)->setPen(QPen(Qt::magenta));
    customPlot->graph(4)->setLineStyle(QCPGraph::lsLine);    //使用直线将点连接
//    customPlot->graph(4)->setScatterStyle(QCPScatterStyle::ssCross);  //x

    for(int index = 1; index<4097; index++)
    {
        ui->DataTable->setColumnWidth(index, 45);
    }

}

QString FiniteAqs::get_datetime(bool flag)
{
    if(flag)
        return QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz\n");
    else
        return QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
}

void FiniteAqs::log_update(const QString& msg)
{
    if(msg.isEmpty())
        return;
    ui->textBrowser->append(get_datetime(true) + msg);
}

void FiniteAqs::data_update(const cv::Mat& mat)
{
    if(0 != ui->tabWidget->currentIndex())
    {
        return;
    }
    //    cout<<mat<<endl;
    if(currentRow >= 4096)
    {
        currentRow = 0;
    }
    //时间
    QTableWidgetItem* item;
    item = new QTableWidgetItem;
    item->setText(QDateTime::currentDateTime().toString("hh:mm:ss.zzz"));
    ui->DataTable->setItem(currentRow, 0, item);
    //数据
    for(int row = 0; row < mat.rows; row++)
    {
        for(int col = 0; col < mat.cols; col++)
        {
            item = new QTableWidgetItem;
            item->setData(0, mat.at<unsigned short>(row, col));
            ui->DataTable->setItem(currentRow, row*mat.cols+col+1, item);
        }
    }
    currentRow++;
}

void FiniteAqs::map_update(const QPixmap& pixmap)
{
    if(1 != ui->tabWidget->currentIndex())
    {
        return;
    }
    ui->label_5->setPixmap(pixmap);
}
void FiniteAqs::curve_update(const cv::Mat& mat)
{
    if(2 != ui->tabWidget->currentIndex())
    {
        return;
    }
    if(lines.size() < 1)
    {
        on_stopAqs_clicked();
        log_update("please add point first.");
        return;
    }
    if(time_datas.size() >= 256)
    {
        time_datas.removeFirst();
        lines_data0.removeFirst();
        lines_data1.removeFirst();
        lines_data2.removeFirst();
        lines_data3.removeFirst();
        lines_data4.removeFirst();
    }
    double now = QDateTime::currentDateTime().currentMSecsSinceEpoch()/1000.0;
//    double now = QTime::currentTime().msecsSinceStartOfDay();
    time_datas.append(now);
    switch (lines.size())
    {
    case 1:
    {
        lines_data0.append((double)mat.at<unsigned short>(lines.at(0).x, lines.at(0).y));
        customPlot->graph(0)->setData(time_datas, lines_data0);
        break;
    }
    case 2:
    {
        lines_data0.append((double)mat.at<unsigned short>(lines.at(0).x, lines.at(0).y));
        customPlot->graph(0)->setData(time_datas, lines_data0);
        lines_data1.append((double)mat.at<unsigned short>(lines.at(1).x, lines.at(1).y));
        customPlot->graph(1)->setData(time_datas, lines_data1);
        break;
    }
    case 3:
    {
        lines_data0.append((double)mat.at<unsigned short>(lines.at(0).x, lines.at(0).y));
        customPlot->graph(0)->setData(time_datas, lines_data0);
        lines_data1.append((double)mat.at<unsigned short>(lines.at(1).x, lines.at(1).y));
        customPlot->graph(1)->setData(time_datas, lines_data1);
        lines_data2.append((double)mat.at<unsigned short>(lines.at(2).x, lines.at(2).y));
        customPlot->graph(2)->setData(time_datas, lines_data2);
        break;
    }
    case 4:
    {
        lines_data0.append((double)mat.at<unsigned short>(lines.at(0).x, lines.at(0).y));
        customPlot->graph(0)->setData(time_datas, lines_data0);
        lines_data1.append((double)mat.at<unsigned short>(lines.at(1).x, lines.at(1).y));
        customPlot->graph(1)->setData(time_datas, lines_data1);
        lines_data2.append((double)mat.at<unsigned short>(lines.at(2).x, lines.at(2).y));
        customPlot->graph(2)->setData(time_datas, lines_data2);
        lines_data3.append((double)mat.at<unsigned short>(lines.at(3).x, lines.at(3).y));
        customPlot->graph(3)->setData(time_datas, lines_data3);
        break;
    }
    case 5:
    {
        lines_data0.append((double)mat.at<unsigned short>(lines.at(0).x, lines.at(0).y));
        customPlot->graph(0)->setData(time_datas, lines_data0);
        lines_data1.append((double)mat.at<unsigned short>(lines.at(1).x, lines.at(1).y));
        customPlot->graph(1)->setData(time_datas, lines_data1);
        lines_data2.append((double)mat.at<unsigned short>(lines.at(2).x, lines.at(2).y));
        customPlot->graph(2)->setData(time_datas, lines_data2);
        lines_data3.append((double)mat.at<unsigned short>(lines.at(3).x, lines.at(3).y));
        customPlot->graph(3)->setData(time_datas, lines_data3);
        lines_data4.append((double)mat.at<unsigned short>(lines.at(4).x, lines.at(4).y));
        customPlot->graph(4)->setData(time_datas, lines_data4);
        break;
    }
    default:
        break;
    }

//    customPlot->graph(0)->rescaleAxes();//自适应
//    customPlot->graph(1)->rescaleAxes();//自适应
//    customPlot->graph(2)->rescaleAxes();//自适应
//    customPlot->graph(3)->rescaleAxes();//自适应
//    customPlot->graph(4)->rescaleAxes();//自适应
//    customPlot->replot();
}

void FiniteAqs::plot_update()
{
    if(2 != ui->tabWidget->currentIndex())
    {
        return;
    }
//    double now = QTime::currentTime().msecsSinceStartOfDay();
    double now = QDateTime::currentDateTime().currentMSecsSinceEpoch()/1000.0;
    customPlot->xAxis->setRange(now-1.0, now);
    for(int index = 0; index<lines.size(); index++)
    {
        customPlot->graph(index)->rescaleAxes();
    }
    customPlot->replot();
}

void FiniteAqs::on_DataAqsBtn_clicked()
{
    if(!Dev5630->AI_InitTask())
        return;
    if(!Dev5630->AI_StartTask())
        return;
    emit call_loop_read();//循环读取
    //    emit call_testAqc();//单次读取测试
    plotTimer->start(500);

    ui->RefGroundBox->setEnabled(false);
    ui->SampRowChanSpinBox->setEnabled(false);
    ui->SampColumChanSpinBox->setEnabled(false);
    ui->SampRangeBox->setEnabled(false);
    ui->fSampRate->setEnabled(false);
    ui->DataClearBtn->setEnabled(false);
    ui->DataSaveBtn->setEnabled(false);

//    QTimer::singleShot(200, this, [=]{
//        if(0 == ui->tabWidget->currentIndex())
//            ui->DataTable->resizeColumnsToContents();
//    });
}

void FiniteAqs::on_stopAqs_clicked()
{
    Dev5630->stop_loop_read();
    plotTimer->stop();
    ui->RefGroundBox->setEnabled(true);
    ui->SampRowChanSpinBox->setEnabled(true);
    ui->SampColumChanSpinBox->setEnabled(true);
    ui->SampRangeBox->setEnabled(true);
    ui->fSampRate->setEnabled(true);
    ui->DataClearBtn->setEnabled(true);
    ui->DataSaveBtn->setEnabled(true);
}

void FiniteAqs::on_setParameter_clicked()
{
    Dev5630->select_RefGround(ui->RefGroundBox->currentIndex());//接线方式
    Dev5630->change_SampChanCount(ui->SampColumChanSpinBox->value());//列，即通道数
    Dev5630->change_SampsPerChan(ui->SampRowChanSpinBox->value());//行，即每通道采样点数
    Dev5630->select_SampleRange(ui->SampRangeBox->currentIndex());//采样范围
    Dev5630->change_SampleRate(ui->fSampRate->value());
    if(!Dev5630->AI_VerifyParam())
    {
        QMessageBox::information(0, "Information", "AI_VerifyParam failed.");
        return;
    }
    ui->DataAqsBtn->setEnabled(true);
}

void FiniteAqs::on_DataClearBtn_clicked()
{
    //清除table和曲线显示
    if(ui->tabWidget->currentIndex() == 0)
    {
        ui->DataTable->clear();
        currentRow = 0;
    }
    else if(ui->tabWidget->currentIndex() == 2)
    {
        customPlot->graph(0)->data().data()->clear();
        customPlot->graph(1)->data().data()->clear();
        customPlot->graph(2)->data().data()->clear();
        customPlot->graph(3)->data().data()->clear();
        customPlot->graph(4)->data().data()->clear();
        customPlot->replot();
        //清除曲线数据
        time_datas.clear();
        lines_data0.clear();
        lines_data1.clear();
        lines_data2.clear();
        lines_data3.clear();
        lines_data4.clear();
    }
    else if(ui->tabWidget->currentIndex() == 1)
    {
        ui->label_5->clear();
    }
}

void FiniteAqs::on_tabWidget_currentChanged(int index)
{
//    if(index == 0)
//    {
//        connect(Dev5630, &Acqure::out_mat, this, &FiniteAqs::data_update);
//        disconnect(Dev5630, &Acqure::out_mat, this, &FiniteAqs::curve_update);
//    }
//    else if(index == 2)
//    {
//        disconnect(Dev5630, &Acqure::out_mat, this, &FiniteAqs::data_update);
//        connect(Dev5630, &Acqure::out_mat, this, &FiniteAqs::curve_update);
//    }
}


void FiniteAqs::on_addPoint_clicked()
{
    int row = ui->pointRow->text().toInt();
    int column = ui->pointCol->text().toInt();
    cv::Point2d curPoint(row, column);
    if(!lines.contains(curPoint))
    {
        if(lines.size() >= 5)   //限制曲线数量为5
        {
           lines.removeFirst();
        }
        lines.append(curPoint);
        log_update(QString("Point(%1, %2) has been appended.").arg(row).arg(column));
    }
}


